package aop;


import domain.ErrorLog;
import domain.Log;
import domain.Programmer;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import service.ErrorLogService;
import service.LogService;
import service.ProgrammerService;
import util.MailUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.Security;
import java.util.Date;
import java.util.List;

@Aspect
@Component
public class LogAop {

    @Autowired
    private ErrorLogService errorLogService;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private LogService logService;

    @Autowired
    private ProgrammerService programmerService;


    //配置切点
    @Pointcut("execution(* controller.*.*(..))")
    public void pointCut(){}

    //前置通知
    @Before("pointCut()")
    public void before(){
        Date visitTime = new Date();
        request.setAttribute("visitTime",visitTime);
    }

    //后置通知
    @AfterReturning("pointCut()")
    public void after(JoinPoint joinPoint){
        Log log = new Log();
        SecurityContext context = SecurityContextHolder.getContext();//获取security容器
        User user = (User) context.getAuthentication().getPrincipal();//获取User对象
        String username = user.getUsername();//获取用户名
        String method = joinPoint.getSignature().getName();//访问方法
        String url = request.getRequestURI();//访问路径
        String ip = request.getLocalAddr();//访问者ip
        int status = 0;//状态
        Date visitTime = (Date) request.getAttribute("visitTime");//访问时间
        long time = new Date().getTime() - visitTime.getTime();//访问时长
        log.setUsername(username);
        log.setMethod(method);
        log.setUrl(url);
        log.setVisitTime(visitTime);
        log.setStatus(status);
        log.setClientIp(ip);
        log.setTime(time);
        logService.addLog(log);
    }

    //异常通知
    @AfterThrowing(pointcut = "pointCut()",throwing = "ex")
    public void exception(JoinPoint joinPoint,Throwable ex){
        ErrorLog errorLog = new ErrorLog();
        SecurityContext context = SecurityContextHolder.getContext();//获取security容器
        User user = (User) context.getAuthentication().getPrincipal();//获取User对象
        String username = user.getUsername();//获取用户名
        String method = joinPoint.getSignature().getName();//访问的方法
        String url = request.getRequestURI();//路径
        String ip = request.getLocalAddr();//访问者ip地址
        int status = 1;//访问状态
        Date visitTime = (Date) request.getAttribute("visitTime");//访问时间
        long time = new Date().getTime() - visitTime.getTime();//访问时长
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        String stackTrace = sw.toString();//异常栈信息
        String message = ex.getMessage();//异常信息
        errorLog.setUsername(username);
        errorLog.setMethod(method);
        errorLog.setUrl(url);
        errorLog.setVisitTime(visitTime);
        errorLog.setStatus(status);
        errorLog.setClientIp(ip);
        errorLog.setExceptionMessage(message);
        errorLog.setStackTrace(stackTrace);
       errorLogService.addErrorLog(errorLog);
        // 将异常发送给程序员
        List<Programmer> programmers = programmerService.findProgrammerByStatus();
        String text="出异常了！<br>" +
                "错误原因:"+message+"<br>" +
                "异常栈信息:"+stackTrace;
        for (Programmer programmer:programmers){
            MailUtils mail = new MailUtils(programmer.getEmail(), text, "旅游管理系统出现异常了！");
            Thread thread = new Thread(mail);
            thread.start();
        }
    }


}
